package com.bsj.media.web;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.bsj.media.config.PortConstant;
import com.bsj.media.init.NettyUDPIntercomUntil;
import com.bsj.media.media.VideoServerCmdType;
import com.bsj.media.network.udpUntil.UDPBackRTPHandle;
import com.bsj.media.network.websocket.CmdConstant;
import com.bsj.media.network.websocket.CmdDto;
import com.bsj.media.tool.HttpPlayBackTool;
import com.bsj.media.tool.HttpPlayVideoTool;
import com.bsj.media.tool.HttpTool;
import com.bsj.power.common.config.cached.RedisCached;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.def.entity.log.VideoOpLog;
import com.bsj.power.common.def.enums.VideoOpTypeEnum;
import com.bsj.power.common.mapper.VideoOpLogMapper;
import com.bsj.power.common.util.DateUtils;
import com.bsj.tools.netty.UdpServiceUntil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.bsj.power.common.util.DateUtils.TIME_STANDARD_FORMAT2;

/**
 * 多媒体控制指令下发
 * @author yinhao
 */
@Slf4j
@RestController
@RequestMapping("/cmd")
public class CmdControl {

    @Autowired
    private RedisCached redisCached;

    @Resource
    private VideoOpLogMapper videoOpLogMapper;


    /**
     * 统一管理设备的直播开启与关闭
     * @param cmdDto
     * @param request
     * @return
     */
    @SaIgnore
    @PostMapping("/cmdControl")
    public JsonResult realVideoReq(@RequestBody CmdDto cmdDto, HttpServletRequest request) {
        JsonResult jsonResult = new JsonResult();
        log.info("传参为:" + JSONObject.toJSONString(cmdDto));
        String simChannel = cmdDto.getSimChannel();
        String sessionId = request.getHeader("power-cookie");
        if (StringUtils.isBlank(simChannel) || simChannel.indexOf("undefined") >= 0 || StringUtils.isBlank(sessionId)) {
            jsonResult.setMsg("无效参数");
            return jsonResult;
        }
        cmdDto.setSimChannel(simChannel);
        String[] split = simChannel.split("-");
        if (split.length == 3) {
            //第三位为端口号
            cmdDto.setPort(Integer.parseInt(split[2]));
        }
        //设备ID
        String terminalNo = split[0];
        int channelNo = Integer.parseInt(split[1]);
        //0是直播，1是回放，3控制
        int videoTypeNow = cmdDto.getVideoType();
        //控制按钮
        if (videoTypeNow == 3) {
            String sim = terminalNo;
//            handleVideoControlCmd(cmdDto, sim, sessionId);
            return JsonResult.success();
            //1是回放
        } else if (videoTypeNow == CmdConstant.BACK) {
            /**
             * 如果是回放的话，先检测上一次的是否有正在播放的
             * 如果有先关闭再播放
             */
            return backHandleCmd(cmdDto, terminalNo, channelNo, sessionId);
            //如果是直播
        } else if (videoTypeNow == CmdConstant.LIVE) {
            return handleVideoCmd(cmdDto, terminalNo, channelNo, sessionId);
        } else {
            log.warn("传参错误:" + videoTypeNow);
            return JsonResult.fail();
        }
    }

    /**
     * 回放时需要新加UDP服务端
     * @param cmdDto
     * @param terminalNo
     * @param channelNo
     * @return
     */
    private JsonResult backHandleCmd(CmdDto cmdDto, String terminalNo, int channelNo, String sessionId) {
        //拉流地址 http://192.168.130.7:20000/media/gainLink?simChannel=3-127.flv&power-cookie=b11179ba-e6e5-4c6b-b2d8-75fea15c0f02
        int videoFlag = cmdDto.getVideoFlag();
        //时间戳
        long millis = System.currentTimeMillis();
        //设备ID
        int devId = Integer.parseInt(terminalNo);
        //{"desc":"open vod 2024-08-13 16:52:50.557","streamType":1,"startTime":1723533230,"endTime":1723539071}
        String str = cmdDto.getStr();
        String down = null;
        if (str != null) {
            //下载使用
            JSONObject object = JSONObject.parseObject(str);
            String objStr = object.getString("down");
            if (StringUtils.isNotEmpty(objStr)) {
                Long startTime = object.getLong("startTime");
                Long endTime = object.getLong("endTime");
                down = DateUtils.dateToStr(TIME_STANDARD_FORMAT2, new Date(startTime * 1000))
                        + "_" + DateUtils.dateToStr(TIME_STANDARD_FORMAT2, new Date(endTime * 1000)) + ".flv";
            }
        }
        //打开回放
        Integer port = null;
        if (videoFlag == CmdConstant.PLAY) {
            //判断开启的回放通道数
//            List<Integer> list = NettyUDPIntercomUntil.gainPort(devId);
//            if (list != null && !list.isEmpty()) {
//                if (list.size() >= 2) {
//                    return JsonResult.fail("录像链路占用中, 请稍后操作");
//                }
//            }
            //先取端口号
            while (true) {
                port = RandomUtil.randomInt(PortConstant.rtpBackPort, 20200);
//                port = PortConstant.rtpBackPort;
                UdpServiceUntil gain = NettyUDPIntercomUntil.gain(port);
                if (gain != null) {
                    //如果端口被占用，则重新获取
                    continue;
                } else {
                    //新增回放控制UDP服务端解析
                    gain = new UdpServiceUntil();
                    gain.start(port, new UDPBackRTPHandle(port));
                    NettyUDPIntercomUntil.push(port, gain);
                    cmdDto.setPort(port);
                    break;
                }
            }
        } else {
            //关闭回放
            port = cmdDto.getPort();
            if (port == null) {
                return JsonResult.fail("关闭回放无效端口号");
            }
            UdpServiceUntil gain = NettyUDPIntercomUntil.gain(port);
            if (gain != null) {
                gain.stop();
            }
        }
        HttpPlayBackTool.cmdLivePlayBack(cmdDto, terminalNo, channelNo);
        channelNo += 126;
        String mediaType = cmdDto.getMediaType() == null ? VideoServerCmdType.MEDIA : cmdDto.getMediaType();
        String url = PortConstant.httpPlayBack + "simChannel=" + terminalNo + "-" + channelNo + "-" + port
                + ".flv&power-cookie=" + sessionId + "&millis=" + millis + "&mediaType=" + mediaType;
        if (down != null) {
            //下载
            url = url + "&downFile=" + down;
        }

        return JsonResult.success(Map.of("flvUrl", url, "port", port));
    }

    /**
     * 直播时
     * @param cmdDto
     * @param terminalNo
     * @param channelNo
     * @param sessionId
     * @return
     */
    private JsonResult handleVideoCmd(CmdDto cmdDto, String terminalNo, int channelNo, String sessionId) {
        //时间戳
        long millis = System.currentTimeMillis();
//        int videoFlag = cmdDto.getVideoFlag();
//        if (videoFlag == 0) {
//            String s = redisCached.get("power-cookie:login:token:" + sessionId);
//            VideoOpLog videoOpLog = new VideoOpLog();
//            videoOpLog.setName("打开直播");
//            videoOpLog.setDeviceId(terminalNo);
//            videoOpLog.setOpUserId(s == null ? 0 : Long.parseLong(s));
//            videoOpLog.setOpType(VideoOpTypeEnum.INSTRUCTION.getOpType());
//            videoOpLog.setOpTime(new Date(millis));
//            videoOpLog.setCreateTime(new Date(millis));
//            videoOpLogMapper.insert(videoOpLog);
//        }
        HttpPlayVideoTool.cmdLiveMedia(cmdDto, terminalNo, channelNo);
        String mediaType = cmdDto.getMediaType() == null ? VideoServerCmdType.MEDIA : cmdDto.getMediaType();
        String url = PortConstant.httpPlayBack + "simChannel=" + terminalNo + "-" + channelNo
                + ".flv&power-cookie=" + sessionId + "&millis" + millis + "&mediaType=" + mediaType;
        return JsonResult.success(url);
    }


//    private JsonResult backHandleCmd(CmdDto cmdDto, String sessionId, String terminalNo, int channelNo) {
//        int videoFlag = cmdDto.getVideoFlag();
//        //回放的通道号需要加126
//        int channelNoNow = channelNo + 126;
//        String key = CmdConstant.CMD_BACK_NAME + terminalNo;
//        //如果是播放回放视频
//        if (videoFlag == CmdConstant.PLAY) {
//            String s = jedisClusterBSJ.get(key);
//            //如果不为空的话，先关闭再开启
//            BackCmdDto backCmdDto = new BackCmdDto();
//            //如果不为空表示上次有人播放过
//            if (StringUtils.isNotBlank(s)) {
//                backCmdDto = JSONObject.parseObject(s, BackCmdDto.class);
//                String sessionIdLast = backCmdDto.getSessionId();
//                //上一次的人还没播放完毕
//                if (!sessionId.equals(sessionIdLast)) {
//                    return JsonResult.fail("无法同时观看回放视频");
//                } else {
//                    int channelNoOld = backCmdDto.getChannelNoNow();
//                    closeVideo(terminalNo, channelNoOld, sessionId);
//                }
//            } else {
//                backCmdDto.setSessionId(sessionId);
//            }
//            backCmdDto.setChannelNoNow(channelNoNow);
//            backCmdDto.setTime(System.currentTimeMillis());
//            String value = JSONObject.toJSONString(backCmdDto);
//            jedisClusterBSJ.set(key, value);
//            //30分钟过期时间
//            jedisClusterBSJ.expire(key, 30 * 60);
//            return handleVideoCmd(cmdDto, terminalNo, channelNo, sessionId);
//            //关闭指令
//        } else if (videoFlag == CmdConstant.CLOSE) {
//            String s = jedisClusterBSJ.get(key);
//            int channelNow = channelNo;
//            if (channelNow < 126) {
//                channelNow = channelNo + 126;
//            }
//            if (StringUtils.isNotBlank(s)) {
//                BackCmdDto backCmdDto = JSONObject.parseObject(s, BackCmdDto.class);
//                channelNow = backCmdDto.getChannelNoNow();
//            }
//            closeVideo(terminalNo, channelNow, sessionId);
//            return JsonResult.success();
//        } else {
//            log.error("无法估计的通道号:" + videoFlag);
//            return JsonResult.paramError();
//        }
//    }

    //关闭
//    private void closeVideo(String terminalNo, int channelNo) {
//        log.info("关闭的sim卡和通道为:" + terminalNo + "/" + channelNo);
//        HttpTool.closeMedia(terminalNo, channelNo);
//    }

//    private JsonResult handleVideoCmd(CmdDto cmdDto, String terminalNo, int channelNo, String sessionId) {
//        CmdVo cmdVo = new CmdVo();
//        //下发相关的http操作
//        String videoId = HttpTool.cmdLiveMedia(cmdDto, terminalNo, channelNo);
//        if (videoId != null) {
//            cmdVo.setVideoId(videoId);
//        }
//        //时间戳
//        long millis = System.currentTimeMillis();
//        String url = httpPlayBack + "simChannel=" + terminalNo + "-" + channelNo
//                + ".flv&power-cookie=" + sessionId + "&millis" + millis;
//        return JsonResult.success(url);
//    }

    /**
     * 回放控制
     * @param cmdDto
     * @param sim
     * @param sessionId
     * @return
     */
//    private String handleVideoControlCmd(CmdDto cmdDto, String sim, String sessionId) {
//        JsonResult jsonResult = new JsonResult();
//        int videoFlag = cmdDto.getVideoFlag();
//        if (videoFlag == 0) {
//            //恢复请求
//            HttpTool.controlBackMedia(sim, 1, 0, sessionId);
//        } else if (videoFlag == 2) {
//            //暂停请求
//            HttpTool.controlBackMedia(sim, 1, 1, sessionId);
//        } else if ( videoFlag == 3 || videoFlag == 4) {
//            //快进/快退
//            HttpTool.controlBackMedia(sim, cmdDto.getStr(), 1, sessionId);
//        }
//        return JSONObject.toJSONString(jsonResult);
//    }
}
